package x.y.z.other;

/**
 * Hello world!
 *
 */

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;

import org.json.JSONObject;

public class Client1 extends Socket {
	static Map<String, String> ma = new HashMap();
	static DesUtils des = new DesUtils("a3VPjsfeF0YmmwVQ");
	//static Socket client ;
	
	private static Socket client;
    private static PrintWriter out;
    private BufferedReader in;

	  static String SERVER_IP ;
	  static int SERVER_PORT ;
	public static void main(String[] args) throws Exception {
		// String path = System.getProperty("user.dir");
		// FileReader fr = new FileReader(path + "\\ctfmon.ini");
		// BufferedReader br = new BufferedReader(fr);
		// String str2 = br.readLine();
		// br.close();
		// fr.close();
		// String ip = getHostIP();
		// String[] str = str2.split("=");
		//start();
		
	    String ip = getHostIP();
		getmap();

		if (ma.get("uuid") == null) {
			setmap();
			getmap();
		}
		SERVER_IP =ma.get("ip")+"";
		SERVER_PORT =Integer.valueOf(ma.get("prot")+"");
		new Client1();
		// getHostIP();
		// String
		// id=UUID.randomUUID().toString();//生成的id942cd30b-16c8-449e-8dc5-028f38495bb5中间含有横杠，<span
		// style="color: rgb(75, 75, 75); font-family: Verdana, Arial, Helvetica,
		// sans-serif; line-height: 20.7999992370605px;">用来生成数据库的主键id是很实用的。</span>

		// System.out.println(id);;

	}
	public Client1() throws Exception{
		 super(SERVER_IP, SERVER_PORT);
		
		
       
        
        client =this;
        out =new PrintWriter(this.getOutputStream(),true);
        in =new BufferedReader(new InputStreamReader(this.getInputStream()));
        new readLineThread();
        Timer timer = new Timer();
		timer.schedule(new TimerTask() {
			@Override
			public void run() {
				try {
					heartbeat( new HashMap<String, Object>());
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}, 0, 60 * 1000);
        while(true){
           // in =new BufferedReader(new InputStreamReader(System.in));
            //String input = in.readLine();
            
        }
    }
     
    /**
     * 用于监听服务器端向客户端发送消息线程类
     */
    class readLineThread extends Thread{
         
        private BufferedReader buff;
        public readLineThread(){
            try {
                buff =new BufferedReader(new InputStreamReader(client.getInputStream()));
                start();
            }catch (Exception e) {
            }
        }
         
        @Override
        public void run() {
            try {
                while(true){
                    String result = buff.readLine();
                    if("byeClient".equals(result)){//客户端申请退出，服务端返回确认退出
                        break;
                    }else{//输出服务端发送消息

    					// 从服务器端接收数据有个时间限制（系统自设，也可以自己设置），超过了这个时间，便会抛出该异常
    					String echo = result;
    					if (echo != null && !"".equals(echo.trim())) {
    						String s = des.decrypt(echo.trim());
    						JSONObject j = new JSONObject(s);
    						String uuid = j.getString("uuid");
    						if (uuid.equals(ma.get("uuid"))) {
    							JSONObject h = j.getJSONObject("content");
    							String vcode = h.getString("vcode");

    							if ("21".equals(vcode) || "22".equals(vcode)) {

    								Map<String, Object> msa = new HashMap<String, Object>();
    								msa.put("type", "2");
    								try {
    									ResultSet rs = null;
    									Connection conn = null;
    									Statement stmt = null;

    									String port = h.getString("port");
    									String username = h.getString("username");
    									String pwd = h.getString("pwd");
    									String databaseName = h.getString("databaseName");
    									String sql = h.getString("sql");
    									String url = "";
    									if ("21".equals(vcode)) {
    										Class.forName("com.mysql.jdbc.Driver");
    										url = "jdbc:mysql://localhost:" + port + "/" + databaseName
    												+ "?useUnicode=true&characterEncoding=UTF8&autoReconnect=true";
    									}
    									if ("22".equals(vcode)) {
    										Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
    										url = "jdbc:sqlserver://localhost:" + port + ";databaseName=" + databaseName;
    									}

    									conn = DriverManager.getConnection(url, username, pwd);
    									stmt = conn.createStatement();

    									if (sql.toLowerCase().indexOf("select") == 0) {
    										rs = stmt.executeQuery(sql);
    										List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
    										ResultSetMetaData md = rs.getMetaData(); // 获得结果集结构信息,元数据
    										int columnCount = md.getColumnCount(); // 获得列数
    										while (rs.next()) {
    											Map<String, Object> rowData = new HashMap<String, Object>();
    											for (int i = 1; i <= columnCount; i++) {
    												rowData.put(md.getColumnName(i), rs.getObject(i));
    											}
    											list.add(rowData);

    										}

    										msa.put("content", list);
    									} else {
    										int rs1 = stmt.executeUpdate(sql);
    										msa.put("content", rs1);
    									}
    								} catch (Exception e) {
    									e.printStackTrace();
    									msa.put("error", e.getMessage());
    								}
    								heartbeat( msa);
    							}
    						}

    					}
    					
                    }
                }
                in.close();
                out.close();
                client.close();
            }catch (Exception e) {
            }
        }
    }
     
	private static void getmap() throws IOException {
		String path = System.getProperty("user.dir");
		FileReader fr = new FileReader(path + "\\ctfmon.ini");
		BufferedReader br = new BufferedReader(fr);
		boolean bo = true;

		while (bo) {
			String str2 = br.readLine();
			if (str2 == null) {
				bo = false;
			} else {
				String[] str = str2.split("=");
				if (str.length > 1) {
					ma.put(str[0], str[1]);
				}
			}
		}

		br.close();
		fr.close();
	}

	private static void setmap() throws IOException {
		String path = System.getProperty("user.dir");

		FileWriter writer = new FileWriter(path + "\\ctfmon.ini", true);
		SimpleDateFormat format = new SimpleDateFormat();
		writer.write("\r\n");
		writer.write("uuid=" + UUID.randomUUID().toString());
		writer.close();

	}

	public static void heartbeat( Map<String, Object> m) throws IOException {
		 //PrintStream out = new PrintStream(client.getOutputStream());
		String code = "0";
		String uuid = ma.get("uuid");
		
		String type = "1";
		String content = getHostIP();
		String error = "";
		String returnmess = "";
		if (m.get("code") != null) {
			code = m.get("code")+"";
		}
		if (m.get("type") != null) {
			type = m.get("type")+"";
		}
		if (m.get("content") != null) {
			content = m.get("content")+"";
		}
		if (m.get("error") != null) {
			error = m.get("error")+"";
		}

		JSONObject json = new JSONObject();
		json.put("code", code).put("type", type).put("content", content)
		.put("uuid", uuid).put("error", error);
		System.out.println(json);
		try {
			returnmess = des.encrypt(json.toString());
			//out.print(returnmess);
			out.println(returnmess);
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
		

	}

	private static void start() throws Exception {
		// 客户端请求与本机在20006端口建立TCP连接

		String ip = getHostIP();
		getmap();

		if (ma.get("uuid") == null) {
			setmap();
			getmap();
		}

		 //client = new Socket(ma.get("ip") + "", Integer.valueOf(ma.get("prot") + ""));
		//client.setSoTimeout(10000);

		// 获取Socket的输出流，用来发送数据到服务端
		
		// 获取Socket的输入流，用来接收从服务端发送过来的数据
		BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream()));
		boolean flag = true;
		Timer timer = new Timer();
		timer.schedule(new TimerTask() {
			@Override
			public void run() {
				try {
					heartbeat( new HashMap<String, Object>());
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}, 0, 60 * 1000);

		while (flag) {
			String str1 = "1";
			if ("bye".equals(str1)) {
				flag = false;
			} else {
				try {
					// 从服务器端接收数据有个时间限制（系统自设，也可以自己设置），超过了这个时间，便会抛出该异常
					String echo = buf.readLine();
					if (echo != null && !"".equals(echo.trim())) {
						String s = des.decrypt(echo.trim());
						JSONObject j = new JSONObject(s);
						String uuid = j.getString("uuid");
						if (uuid.equals(ma.get("uuid"))) {
							JSONObject h = j.getJSONObject("content");
							String vcode = h.getString("vcode");

							if ("21".equals(vcode) || "22".equals(vcode)) {

								Map<String, Object> msa = new HashMap<String, Object>();
								msa.put("type", "2");
								try {
									ResultSet rs = null;
									Connection conn = null;
									Statement stmt = null;

									String port = h.getString("port");
									String username = h.getString("username");
									String pwd = h.getString("pwd");
									String databaseName = h.getString("databaseName");
									String sql = h.getString("sql");
									String url = "";
									if ("21".equals(vcode)) {
										Class.forName("com.mysql.jdbc.Driver");
										url = "jdbc:mysql://localhost:" + port + "/" + databaseName
												+ "?useUnicode=true&characterEncoding=UTF8&autoReconnect=true";
									}
									if ("22".equals(vcode)) {
										Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
										url = "jdbc:sqlserver://localhost:" + port + ";databaseName=" + databaseName;
									}

									conn = DriverManager.getConnection(url, username, pwd);
									stmt = conn.createStatement();

									if (sql.toLowerCase().indexOf("select") == 0) {
										rs = stmt.executeQuery(sql);
										List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
										ResultSetMetaData md = rs.getMetaData(); // 获得结果集结构信息,元数据
										int columnCount = md.getColumnCount(); // 获得列数
										while (rs.next()) {
											Map<String, Object> rowData = new HashMap<String, Object>();
											for (int i = 1; i <= columnCount; i++) {
												rowData.put(md.getColumnName(i), rs.getObject(i));
											}
											list.add(rowData);

										}

										msa.put("content", list);
									} else {
										int rs1 = stmt.executeUpdate(sql);
										msa.put("content", rs1);
									}
								} catch (Exception e) {
									e.printStackTrace();
									msa.put("error", e.getMessage());
								}
								heartbeat( msa);
							}
						}

					}
					
				} catch (SocketTimeoutException e) {
					System.out.println("Time out, No response");
				}
			}
		}

		if (client != null) {
			// 如果构造函数建立起了连接，则关闭套接字，如果没有建立起连接，自然不用关闭
			client.close(); // 只关闭socket，其关联的输入输出流也会被关闭
		}
	}

	/**
	 * 获取ip地址
	 * 
	 * @return
	 */
	public static String getHostIP() {

		List li = new ArrayList();
		try {
			Enumeration nis = NetworkInterface.getNetworkInterfaces();
			InetAddress ia = null;

			while (nis.hasMoreElements()) {
				NetworkInterface ni = (NetworkInterface) nis.nextElement();
				Enumeration<InetAddress> ias = ni.getInetAddresses();
				while (ias.hasMoreElements()) {
					ia = ias.nextElement();
					if (ia instanceof Inet6Address) {
						continue;// skip ipv6
					}
					String ip = ia.getHostAddress();
					li.add(ip);

				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return li.toString();

	}

	private static String getMACAddress() throws Exception {
		InetAddress ia = InetAddress.getLocalHost();
		// 获得网络接口对象（即网卡），并得到mac地址，mac地址存在于一个byte数组中。
		byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();

		// 下面代码是把mac地址拼装成String
		StringBuffer sb = new StringBuffer();

		for (int i = 0; i < mac.length; i++) {
			if (i != 0) {
				sb.append("-");
			}
			// mac[i] & 0xFF 是为了把byte转化为正整数
			String s = Integer.toHexString(mac[i] & 0xFF);
			sb.append(s.length() == 1 ? 0 + s : s);
		}

		// 把字符串所有小写字母改为大写成为正规的mac地址并返回
		return sb.toString().toUpperCase().replaceAll("-", "");
	}
}
